package cn.iocoder.lw.module.core.service.device;

import cn.hutool.core.collection.CollUtil;
import cn.iocoder.lw.framework.common.pojo.PageResult;
import cn.iocoder.lw.framework.common.util.object.BeanUtils;
import cn.iocoder.lw.module.core.controller.admin.device.vo.*;
import cn.iocoder.lw.module.core.convert.device.CoreDeviceConvert;
import cn.iocoder.lw.module.core.dal.dataobject.device.CoreDeviceDO;
import cn.iocoder.lw.module.core.dal.dataobject.project.CoreProjectDO;
import cn.iocoder.lw.module.core.dal.mysql.device.CoreDeviceMapper;
import cn.iocoder.lw.module.core.service.project.CoreProjectService;
import cn.iocoder.lw.module.system.api.dept.DeptApi;
import cn.iocoder.lw.module.system.api.dept.dto.DeptRespDTO;
import cn.iocoder.lw.module.system.api.user.AdminUserApi;
import cn.iocoder.lw.module.system.api.user.dto.AdminUserRespDTO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import jakarta.annotation.Resource;
import java.time.LocalDateTime;
import java.util.Collection;
import java.util.List;
import java.util.Map;

import static cn.iocoder.lw.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.lw.module.core.enums.ErrorCodeConstants.DEVICE_NOT_EXISTS;

/**
 * 核心设备 Service 实现类
 *
 * @author Lw源码
 */
@Service
@Slf4j
public class CoreDeviceServiceImpl implements CoreDeviceService {

    @Resource
    private CoreDeviceMapper deviceMapper;

    @Resource
    private CoreProjectService projectService;

    @Resource
    private AdminUserApi adminUserApi;
    @Resource
    private DeptApi deptApi;

    @Override
    public Long createDevice(CoreDeviceSaveReqVO createReqVO) {
        // 校验项目存在
        projectService.validateProjectExists(createReqVO.getProjectId());

        // 插入
        CoreDeviceDO device = CoreDeviceConvert.INSTANCE.convert(createReqVO);
        deviceMapper.insert(device);
        // 返回
        return device.getId();
    }

    @Override
    public void updateDevice(CoreDeviceSaveReqVO updateReqVO) {
        // 校验存在
        validateDeviceExists1(updateReqVO.getId());

        // 校验项目存在
        projectService.validateProjectExists(updateReqVO.getProjectId());

        // 更新
        CoreDeviceDO updateObj = CoreDeviceConvert.INSTANCE.convert(updateReqVO);
        deviceMapper.updateById(updateObj);
    }

    @Override
    public void deleteDevice(Long id) {
        // 校验存在
        validateDeviceExists1(id);
        // 删除
        deviceMapper.deleteById(id);
    }

    private CoreDeviceDO validateDeviceExists1(Long id) {
        if (id == null) {
            return null;
        }
        CoreDeviceDO device = deviceMapper.selectById(id);
        if (device == null) {
            throw exception(DEVICE_NOT_EXISTS);
        }
        return device;
    }

    @Override
    public CoreDeviceRespVO getDevice(Long id) {
        CoreDeviceDO device = deviceMapper.selectById(id);
        if (device == null) {
            return null;
        }

        CoreDeviceRespVO respVO = CoreDeviceConvert.INSTANCE.convert(device);

        // 设置质保是否过期
        if (respVO.getWarrantyEndTime() != null) {
            respVO.setIsWarrantyExpired(respVO.getWarrantyEndTime().isBefore(LocalDateTime.now()));
        }

        // 填充关联信息
        fillDeviceInfo(respVO);
        return respVO;
    }

    @Override
    public PageResult<CoreDeviceRespVO> getDevicePage(CoreDevicePageReqVO pageReqVO) {
        PageResult<CoreDeviceDO> pageResult = deviceMapper.selectPage(pageReqVO);
        PageResult<CoreDeviceRespVO> respPageResult = CoreDeviceConvert.INSTANCE.convertPage(pageResult);

        // 填充关联信息
        return respPageResult;
    }

    @Override
    public PageResult<CoreDeviceImportExcelVO> getDeviceList(CoreDevicePageReqVO pageReqVO) {
        PageResult<CoreDeviceDO> pageResult = deviceMapper.selectPage(pageReqVO);
        return BeanUtils.toBean(pageResult, CoreDeviceImportExcelVO.class);
    }

    @Override
    public void validateDeviceExists(Long id) {
        validateDeviceExists1(id);
    }

    @Override
    public List<CoreDeviceRespVO> getDeviceListByProjectId(Long projectId) {
        List<CoreDeviceDO> devices = deviceMapper.selectListByProjectId(projectId);
        List<CoreDeviceRespVO> respVOs = CoreDeviceConvert.INSTANCE.convertList(devices);

        // 设置质保是否过期
        respVOs.forEach(vo -> {
            if (vo.getWarrantyEndTime() != null) {
                vo.setIsWarrantyExpired(vo.getWarrantyEndTime().isBefore(LocalDateTime.now()));
            }
        });

        return respVOs;
    }

    @Override
    public long countByProjectIdAndStatus(Long projectId, Integer status) {
        return deviceMapper.selectCountByProjectIdAndStatus(projectId, status);
    }

    /**
     * 设置设备的关联信息
     *
     * @param device 设备
     */
    private void fillDeviceInfo(CoreDeviceRespVO device) {
        if (device == null) {
            return;
        }

        // 填充项目信息
        if (device.getProjectId() != null) {
            CoreProjectDO project = projectService.getProjectRaw(device.getProjectId());
            if (project != null) {
                device.setProjectName(project.getName());
                device.setOwnerUserName(getUserName(project.getOwnerUserId()));
                device.setOwnerDeptName(getDeptName(getUserDeptId(project.getOwnerUserId())));
            }
        }
    }

    /**
     * 根据用户ID获取用户名
     */
    private String getUserName(Long userId) {
        if (userId == null) {
            return null;
        }
        AdminUserRespDTO user = adminUserApi.getUser(userId);
        return user != null ? user.getNickname() : null;
    }

    /**
     * 根据用户ID获取部门ID
     */
    private Long getUserDeptId(Long userId) {
        if (userId == null) {
            return null;
        }
        AdminUserRespDTO user = adminUserApi.getUser(userId);
        return user != null ? user.getDeptId() : null;
    }

    /**
     * 根据部门ID获取部门名
     */
    private String getDeptName(Long deptId) {
        if (deptId == null) {
            return null;
        }
        DeptRespDTO dept = deptApi.getDept(deptId);
        return dept != null ? dept.getName() : null;
    }

}